#pragma once
#include "CScrLanguage.h"

class CConsoleClass;
class CConsoleIdentifier;

enum eConsoleVarType
{
	CONSOLE_INT_VAR,
	CONSOLE_FLOAT_VAR,
	CONSOLE_STRING_VAR,
};

class CConsoleObject : public CIdentifier
{
protected:
	CConsoleObject(const char * szName) : CIdentifier(szName)
	{
	}

private:
	void InvalidAction()
	{
	}

	virtual void					SetValue(int)			{InvalidAction();}
	virtual void					SetValue(float)			{InvalidAction();}
	//virtual void					SetValue(const char *)	{InvalidAction();}
	virtual void					SetValue(std::string)	{InvalidAction();}

};
class CConsoleValueInt : public CConsoleObject
{
	int					m_nValue;

public:
	CConsoleValueInt(const char * szName) : CConsoleObject(szName)
	{
	}
	CConsoleValueInt(const char * szName, int val) : CConsoleObject(szName),
		m_nValue(val)
	{
	}

public:
	void							SetValue(int v)						{m_nValue = v;}
};
class CConsoleValueFloat : public CConsoleObject
{
	float				m_fValue;

public:
	CConsoleValueFloat(const char * szName) : CConsoleObject(szName)
	{
	}
	CConsoleValueFloat(const char * szName, float val) : CConsoleObject(szName),
		m_fValue(val)
	{
	}

public:
	void							SetValue(float v)					{m_fValue = v;}
};
class CConsoleString : public CConsoleObject
{
	char			*	m_szString;
	size_t				m_nLength;
	size_t				m_nMaxLength;
	DWORD				m_dwHash;

	void Init()
	{
		m_szString = nullptr;
		m_nLength = 0;
		m_nMaxLength = 0;
		m_dwHash = 0xFFFFFFFF;
	}
	void Set(const char * str)
	{
		if(str && *str)
		{
			m_nLength = strlen(str) & 0x1FFF;
			for(m_nMaxLength = 0x10; m_nMaxLength <= m_nLength; m_nMaxLength <<= 1);
			m_szString = new char[m_nMaxLength];
			szncpy(m_szString, str, m_nLength+1);
			m_dwHash = GenerateHash(m_szString, m_nLength);
		}
		else if(m_szString)
		{
			if(*m_szString)
			{
				*m_szString = '\0';
				m_nLength = 0;
				m_dwHash = 0xFFFFFFFF;
			}
		}
	}

public:
	CConsoleString(const char * szName) : CConsoleObject(szName)
	{
		Init();
	}
	CConsoleString(const char * szName, const char * str) : CConsoleObject(szName)
	{
		Init();
		Set(str);
	}

public:
};
class CConsoleClass : public CConsoleObject
{
	CList<CConsoleObject>		m_Members;

	CConsoleObject * Append(CConsoleObject * pConsoleObject)
	{
		m_Members.Add(pConsoleObject->GetHash(), pConsoleObject);
		return pConsoleObject;
	}
	CConsoleObject * Find(const char * szName, DWORD dwHash)
	{
		return m_Members.Get(dwHash);
	}
	
public:
	CConsoleClass(const char * szName) : CConsoleObject(szName)
	{
	}
	/*
template<class T>
	CConsoleVar<T> & Add(CConsoleVar<T> * pConsoleVar)
	{
		Append(pConsoleVar);
		return *pConsoleVar;
	}
template<class T>
	CConsoleVar<T> & Get(const char * szName)
	{
		if(auto pObj = (CConsoleVar<T>*)Find(szName, GenerateHash(szName)))
			return *pObj;
		return Append<T>(new CConsoleVar<T>(szName));
	}*/
};

class CConsole : public CConsoleClass
{
public:
	CConsole() : CConsoleClass("SCRambl")
	{
	}
};